;*******************************************************************************
;* @item     CosyOS-II Port
;* @file     port_cmx_s.s
;* @brief    CMSIS Cortex-M Core Port File
;* @author   迟凯峰
;* @version  V3.0.1
;* @date     2024.07.12
;*******************************************************************************
;* <<< Use Configuration Wizard in Context Menu >>>
;
; <e> 是否启用thumb汇编移植方案？
; <i> 启用该方案后，如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; <i> 用户另需在下方（Line 45、46）手动修改 PendSV_Handler 为 XXX_IRQHandler。
CMXPRT_THUMB			EQU		0
; <o> 指令集架构
; <0=> ARMv6-M <1=> ARMv7-M
CMXPRT_ISA              EQU		0
;
; <q> 是否启用DEBUG接口并同时启用任务PC监控？
SYSCFG_TASKPC_MONITOR	EQU		1
;
; <e> 是否启用PendSV_FIFO？
CMXPRT_PENDSVFIFO		EQU		1
; <o> PendSV_FIFO互斥访问方案
; <0=> 全局寄存器变量 <1=> 互斥访问指令 <2=> 关中断
MCUCFG_PENDSVFIFO_MUTEX	EQU		2
; </e>
; <q> 是否启用硬件浮点单元？
MCUCFG_HARDWAREFPU		EQU		0
; </e>
;
;///////////////////////////////////////////////////////////////////////////////

				IF CMXPRT_THUMB == 1

				THUMB
				AREA    |.text|, CODE, READONLY

;///////////////////////////////////////////////////////////////////////////////

; PendSV软中断
; 如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; 需在下方手动修改 PendSV_Handler 为 XXX_IRQHandler。

PendSV_Handler	PROC	;用户手动修改 PendSV_Handler 为 XXX_IRQHandler
				EXPORT	PendSV_Handler	;用户手动修改 PendSV_Handler 为 XXX_IRQHandler

				IF CMXPRT_ISA == 0
				IF MCUCFG_PENDSVFIFO_MUTEX == 0
MCUCFG_CALLEE_PUSH_REG	EQU		24
				ELSE
MCUCFG_CALLEE_PUSH_REG	EQU		32
				ENDIF
				ENDIF

				IMPORT	sPendSV_Handler
				IMPORT	s_task_current
				IMPORT	s_task_news
				PRESERVE8

				push	{lr}

				bl		sPendSV_Handler
;// ?RETURN
				IF		CMXPRT_ISA == 0
				cmp		r0, #0
				beq		__RETURN
				ELSE
				cbz		r0, __RETURN
				ENDIF

				isb
;// ?PROTECTING
				ldr		r1, =s_task_current
				subs	r0, #1
				IF		CMXPRT_ISA == 0
				cmp		r0, #0
				beq		__RESTORE
				ELSE
				cbz		r0, __RESTORE
				ENDIF

				mrs		r0, psp
;// 任务PC监控
			IF	SYSCFG_TASKPC_MONITOR == 1

				IMPORT	s_sign_taskmgr
				IMPORT	s_pc
				ldr		r3, =s_sign_taskmgr
				ldrb	r3, [r3]
				IF		CMXPRT_ISA == 0
				cmp		r3, #0
				beq		__PROTECTING
				ELSE
				cbz		r3, __PROTECTING
				ENDIF
				mov		r3, r0
				adds	r3, #24
				ldmia	r3, {r2}
				ldr		r3, =s_pc
				str		r2, [r3]

			ENDIF
;// 保护现场
__PROTECTING
			IF	MCUCFG_HARDWAREFPU == 1
				vstmdb	r0!, {s16-s31}
			ENDIF

			IF	CMXPRT_ISA == 0

				subs	r0, #MCUCFG_CALLEE_PUSH_REG
				ldr		r2, [r1]
				str		r0, [r2]
				stmia	r0!, {r4-r7}
				mov		r4, r8
				mov		r5, r9
				IF		MCUCFG_PENDSVFIFO_MUTEX == 0
				stmia	r0!, {r4-r5}
				ELSE
				mov		r6, r10
				mov		r7, r11
				stmia	r0!, {r4-r7}
				ENDIF

			ELSE

				IF		MCUCFG_PENDSVFIFO_MUTEX == 0
				stmdb	r0!, {r4-r9}
				ELSE
				stmdb	r0!, {r4-r11}
				ENDIF
				ldr		r2, [r1]
				str		r0, [r2]

			ENDIF
;// 恢复现场
__RESTORE		ldr		r3, =s_task_news
				ldr		r3, [r3]
				str		r3, [r1]
				ldr		r0, [r3]

			IF	CMXPRT_ISA == 0

				adds	r0, #16
				IF		MCUCFG_PENDSVFIFO_MUTEX == 0
				ldmia	r0!, {r4-r5}
				ELSE
				ldmia	r0!, {r4-r7}
				mov		r11, r7
				mov		r10, r6
				ENDIF
				mov		r9, r5
				mov		r8, r4
				mov		r1, r0
				subs	r1, #MCUCFG_CALLEE_PUSH_REG
				ldmia	r1!, {r4-r7}

			ELSE

				IF		MCUCFG_PENDSVFIFO_MUTEX == 0
				ldmia	r0!, {r4-r9}
				ELSE
				ldmia	r0!, {r4-r11}
				ENDIF

			ENDIF

			IF	MCUCFG_HARDWAREFPU == 1
				vldmia	r0!, {s16-s31}
			ENDIF

				msr		psp, r0

__RETURN		pop		{pc}

				ALIGN

				ENDP

;///////////////////////////////////////////////////////////////////////////////

; 中断挂起服务装载器

				IF		CMXPRT_PENDSVFIFO == 1

mPendSV_FIFOLoader\
				PROC
				EXPORT	mPendSV_FIFOLoader

				IMPORT	mPendSV_FIFO_P0
				IMPORT	mPendSV_FIFO_P1
				IMPORT	m_sign_fifo

				ldr		r3, =m_sign_fifo
				ldrb	r3, [r3]
				IF		CMXPRT_ISA == 0
				cmp		r3, #0
				beq		__FIFO1
				ELSE
				cbz		r3, __FIFO1
				ENDIF

			IF	MCUCFG_PENDSVFIFO_MUTEX == 0

__FIFO0			str		r0, [r10,#4]!
				bx		lr

__FIFO1			str		r0, [r11,#4]!
				bx		lr

			ELSE

__FIFO0			ldr		r1, =mPendSV_FIFO_P0
				b		__LOAD

__FIFO1			ldr		r1, =mPendSV_FIFO_P1

				IF		MCUCFG_PENDSVFIFO_MUTEX == 1

__LOAD			ldrex	r2, [r1]
				adds	r2, #4
				strex	r3, r2, [r1]
				cmp		r3, #0
				bne		__LOAD

				ELIF	MCUCFG_PENDSVFIFO_MUTEX == 2

__LOAD			mrs		r3, primask
				cpsid	i
				ldr		r2, [r1]
				adds	r2, #4
				str		r2, [r1]
				msr		primask, r3

				ENDIF

				str		r0, [r2]
				bx		lr

			ENDIF

				ALIGN

				ENDP

				ENDIF

;///////////////////////////////////////////////////////////////////////////////

				ENDIF

				END
